# -*- coding: iso-8859-2 -*-

import string

from authorshipanalyzer.message import RequotationType
from authorshipanalyzer.utils import boolSetter
from authorshipanalyzer.utils import dictSetter

class AuthorSlot:
    '''
    Keep and process all data linked with the same author
    Attributes:
    
    @param slots: list of slot with the same author
    @param author
    
    Content features:
    @param categories: dict<category, frequency factor>, all categories included (0.0 if not occur)
    
    Email structure features:
    @param requotation types = dict of requotation types
    @param greetings: list of greetings
    @param farewells: list of farewells
    @param signature: signature frequency factory
    @param adverts: adverts frequency factor
    @param useDiacritics: bool
    
    Profile features:
    @param age
    @param sex
    @param status
    
    Error features:
    @param eOrthographic: number of orthographic error per word
    @param eShift: number of shift errors per word
    @param eKeyboard: number of keyboard errors per word
    @param eOther: number of unclassified words per word
    
    Stylometric features:
    1. Character based features (starts with 'c'):
    C - total number of characters
    @param cAlphabetic: number of alphabetic characters / C
    @param cUpperCase: number of upper case letters / C
    @param cDigit: number of digits / C
    @param cWhiteSpace: number of white space characters / C
    @param cSpace: number of space / C
    @param cSpacePerWhite: number of space / number of white characters
    @param cTab: number of tabs / C
    @param cTabPerWhite: number of of tabs / number of white characters 
    @param cPunctuation: number of punctuations / C
    
    2. Word based features (starts with 'w'):
    N - total number of words
    V - number of distinct words
    @param wAvgWordLength: average word length
    @param wVocabularyRichness: V / N
    @param wFunctionWord: total number of function words / N
    @param wShortWOrds: number of short words (length of word <= 3) / N
    @param wHapaxLegomentaN: count of hapax legomena / N
    @param wHapaxLegomentaV: count of hapax legomena / V
    @param wPos: dict<part-of-speech, frequency / total number of recognized POS word>
    
    3. Document based features (starts with 'd'):
    @param dBlankLines: number of blank lines / total number of lines
    @param dSentences: number of sentences / number of statements
    
    @param wordFrequency: dict<word_basic_form, frequency>
    '''
    
    def __init__(self):
        self.slots = []
        
        self.categories = {}
        
        self.age = []
        self.status = []
        self.sex = "unknown"

        self.requotationTypes = {}
        self.greetings = {}
        self.farewells = {}
        self.signature = 0.0
        self.advertIndicator = 0.0
        self.useDiacritics = None
        
        self.eOrthographic = 0.0
        self.eShift = 0.0
        self.eKeyboard = 0.0
        self.eOther = 0.0
        
        self.cAlphabetic = 0
        self.cUpperCase = 0
        self.cDigit = 0
        self.cWhiteSpace = 0
        self.cSpace = 0
        self.cSpacePerWhite = 0
        self.cTab = 0
        self.cTabPerWhite = 0 
        self.cPunctuation = {}
        
        self.wAvgWordLength = 0.0
        self.wVocabularyRichness = 0.0
        self.wFunctionWord = 0.0
        self.wShortWords = 0.0
        self.wHapaxLegomentaN = 0.0
        self.wHapaxLegomentaV = 0.0
        self.wPos = {}
        
        self.dBlankLines = 0.0
        self.dSentences = 0.0
        
        self.wordFrequency = {}
        
    def getFeaturesVector(self, selector, authorSlot):
        '''
        @param selector: dict<feature_name, bool>
        @result vector of selected features
        '''
        result = []
        
        if selector["features.document"]:
            result.extend(self.getDocumentFeaturesVector())
            
        if selector["features.word"]:
            result.extend(self.getWordFeaturesVector())
                          
        if selector["features.char"]:
            result.extend(self.getCharFeaturesVector())
            
        if selector["features.punctuation"]:
            result.extend(self.getPunctuationFeaturesVector(authorSlot.cPunctuation.keys()))
            
        if selector["features.error"]:
            result.extend(self.getErrorFeaturesVector())
            
        if selector["features.email"]:
            result.extend(self.getEmailFeaturesVector())
            
        if selector["features.emailrel"]:
            result.extend(self.getEmailRelativeFeaturesVector(authorSlot))
            
        if selector["features.category"]:
            result.extend(self.getCategoriesFeaturesVector(authorSlot))
        
        return result

    def getDocumentFeaturesVector(self):
        return [ self.dBlankLines, self.dSentences]
    
    def getWordFeaturesVector(self):
        result = [ self.wAvgWordLength, self.wVocabularyRichness, self.wFunctionWord, \
                  self.wShortWords, self.wHapaxLegomentaN, self.wHapaxLegomentaV, \
                  dictSetter(self.wPos, "noun"), \
                  dictSetter(self.wPos, "verb"), \
                  dictSetter(self.wPos, "adjective"), \
                  dictSetter(self.wPos, "numeral"), \
                  dictSetter(self.wPos, "pronoun"), \
                  dictSetter(self.wPos, "adverb"), \
                  dictSetter(self.wPos, "conjunction"), \
                  dictSetter(self.wPos, "unknown")]
        return result

    def getCharFeaturesVector(self):
        result = [ self.cAlphabetic, \
            self.cUpperCase, \
            self.cDigit, \
            self.cWhiteSpace, \
            self.cSpace, \
            self.cSpacePerWhite, \
            self.cTab, \
            self.cTabPerWhite]
        return result
    
    def getPunctuationFeaturesVector(self, punctuations = string.punctuation):
        result = []
        for punctuation in punctuations:
            result.append(dictSetter(self.cPunctuation, punctuation))
        return result
    
    def getErrorFeaturesVector(self):
        return [ self.eOrthographic, self.eShift, self.eKeyboard, self.eOther ]
    
    def getEmailFeaturesVector(self):
        result = [ dictSetter(self.requotationTypes, RequotationType.O), \
                   dictSetter(self.requotationTypes, RequotationType.R), \
                   dictSetter(self.requotationTypes, RequotationType.OR), \
                   dictSetter(self.requotationTypes, RequotationType.RO), \
                   dictSetter(self.requotationTypes, RequotationType.ROR), \
                   dictSetter(self.requotationTypes, RequotationType.ORO), \
                   self.signature, \
                   self.advertIndicator ]
        return result
    
    def getEmailRelativeFeaturesVector(self, compAuthorSlot):
        result = []
        for greet in compAuthorSlot.greetings.keys():
            result.append(dictSetter(self.greetings, greet))
        
        for farewell in compAuthorSlot.farewells.keys():
            result.append(dictSetter(self.farewells, farewell))
                          
        return result

    # To make sure that categories appear in the same order send compAuthorSlot
    # as parameter
    def getCategoriesFeaturesVector(self, compAuthorSlot):
        result = []
        for category in compAuthorSlot.categories.keys():
            result.append(self.categories[category])
        return result

    def getEOrthographic(self):
        return self.__eOrthographic


    def getEShift(self):
        return self.__eShift


    def getEKeyboard(self):
        return self.__eKeyboard


    def setEOrthographic(self, value):
        self.__eOrthographic = value


    def setEShift(self, value):
        self.__eShift = value


    def setEKeyboard(self, value):
        self.__eKeyboard = value


    def getSlots(self):
        return self.__slots


    def getCategories(self):
        return self.__categories


    def getAge(self):
        return self.__age


    def getStatus(self):
        return self.__status


    def getSex(self):
        return self.__sex


    def getRequotationTypes(self):
        return self.__requotationTypes


    def getGreetings(self):
        return self.__greetings


    def getFarewells(self):
        return self.__farewells


    def getSignature(self):
        return self.__signature


    def getAdvertIndicator(self):
        return self.__advertIndicator


    def getUseDiacritics(self):
        return self.__useDiacritics


    def getCAlphabetic(self):
        return self.__cAlphabetic


    def getCUpperCase(self):
        return self.__cUpperCase


    def getCDigit(self):
        return self.__cDigit


    def getCWhiteSpace(self):
        return self.__cWhiteSpace


    def getCSpace(self):
        return self.__cSpace


    def getCSpacePerWhite(self):
        return self.__cSpacePerWhite


    def getCTab(self):
        return self.__cTab


    def getCTabPerWhite(self):
        return self.__cTabPerWhite


    def getCPunctuation(self):
        return self.__cPunctuation


    def getWAvgWordLength(self):
        return self.__wAvgWordLength


    def getWVocabularyRichness(self):
        return self.__wVocabularyRichness


    def getWFunctionWord(self):
        return self.__wFunctionWord


    def getWShortWords(self):
        return self.__wShortWords


    def getWHapaxLegomentaN(self):
        return self.__wHapaxLegomentaN


    def getWHapaxLegomentaV(self):
        return self.__wHapaxLegomentaV


    def getWPos(self):
        return self.__wPos


    def getDBlankLines(self):
        return self.__dBlankLines


    def getDSentences(self):
        return self.__dSentences


    def getWordFrequency(self):
        return self.__wordFrequency


    def setSlots(self, value):
        self.__slots = value


    def setCategories(self, value):
        self.__categories = value


    def setAge(self, value):
        self.__age = value


    def setStatus(self, value):
        self.__status = value


    def setSex(self, value):
        self.__sex = value


    def setRequotationTypes(self, value):
        self.__requotationTypes = value


    def setGreetings(self, value):
        self.__greetings = value


    def setFarewells(self, value):
        self.__farewells = value


    def setSignature(self, value):
        self.__signature = value


    def setAdvertIndicator(self, value):
        self.__advertIndicator = value


    def setUseDiacritics(self, value):
        self.__useDiacritics = value


    def setCAlphabetic(self, value):
        self.__cAlphabetic = value


    def setCUpperCase(self, value):
        self.__cUpperCase = value


    def setCDigit(self, value):
        self.__cDigit = value


    def setCWhiteSpace(self, value):
        self.__cWhiteSpace = value


    def setCSpace(self, value):
        self.__cSpace = value


    def setCSpacePerWhite(self, value):
        self.__cSpacePerWhite = value


    def setCTab(self, value):
        self.__cTab = value


    def setCTabPerWhite(self, value):
        self.__cTabPerWhite = value


    def setCPunctuation(self, value):
        self.__cPunctuation = value


    def setWAvgWordLength(self, value):
        self.__wAvgWordLength = value


    def setWVocabularyRichness(self, value):
        self.__wVocabularyRichness = value


    def setWFunctionWord(self, value):
        self.__wFunctionWord = value


    def setWShortWords(self, value):
        self.__wShortWords = value


    def setWHapaxLegomentaN(self, value):
        self.__wHapaxLegomentaN = value


    def setWHapaxLegomentaV(self, value):
        self.__wHapaxLegomentaV = value


    def setWPos(self, value):
        self.__wPos = value


    def setDBlankLines(self, value):
        self.__dBlankLines = value


    def setDSentences(self, value):
        self.__dSentences = value


    def setWordFrequency(self, value):
        self.__wordFrequency = value

    def getAuthor(self):
        return self.slots[0].author    
    
    def addSlot(self, slot):
        '''
        Add slot to list of slots
        '''
        self.slots.append(slot)

    author = property(getAuthor, None, None, None)

    slots = property(getSlots, setSlots, None, None)

    categories = property(getCategories, setCategories, None, None)

    age = property(getAge, setAge, None, None)
    status = property(getStatus, setStatus, None, None)
    sex = property(getSex, setSex, None, None)

    requotationTypes = property(getRequotationTypes, setRequotationTypes, None, None)
    greetings = property(getGreetings, setGreetings, None, None)
    farewells = property(getFarewells, setFarewells, None, None)
    signature = property(getSignature, setSignature, None, None)
    advertIndicator = property(getAdvertIndicator, setAdvertIndicator, None, None)
    useDiacritics = property(getUseDiacritics, setUseDiacritics, None, None)

    cAlphabetic = property(getCAlphabetic, setCAlphabetic, None, None)
    cUpperCase = property(getCUpperCase, setCUpperCase, None, None)
    cDigit = property(getCDigit, setCDigit, None, None)
    cWhiteSpace = property(getCWhiteSpace, setCWhiteSpace, None, None)
    cSpace = property(getCSpace, setCSpace, None, None)
    cSpacePerWhite = property(getCSpacePerWhite, setCSpacePerWhite, None, None)
    cTab = property(getCTab, setCTab, None, None)
    cTabPerWhite = property(getCTabPerWhite, setCTabPerWhite, None, None)
    cPunctuation = property(getCPunctuation, setCPunctuation, None, None)

    wAvgWordLength = property(getWAvgWordLength, setWAvgWordLength, None, None)
    wVocabularyRichness = property(getWVocabularyRichness, setWVocabularyRichness, None, None)
    wFunctionWord = property(getWFunctionWord, setWFunctionWord, None, None)
    wShortWords = property(getWShortWords, setWShortWords, None, None)
    wHapaxLegomentaN = property(getWHapaxLegomentaN, setWHapaxLegomentaN, None, None)
    wHapaxLegomentaV = property(getWHapaxLegomentaV, setWHapaxLegomentaV, None, None)
    wPos = property(getWPos, setWPos, None, None)

    dBlankLines = property(getDBlankLines, setDBlankLines, None, None)
    dSentences = property(getDSentences, setDSentences, None, None)

    wordFrequency = property(getWordFrequency, setWordFrequency, None, None)

    eOrthographic = property(getEOrthographic, setEOrthographic, None, None)
    eShift = property(getEShift, setEShift, None, None)
    eKeyboard = property(getEKeyboard, setEKeyboard, None, None)

            